package com.ssy.lingxi.pay.serviceimpl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ssy.lingxi.common.constant.order.OrderPaymentParameterEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberInnerControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignIdVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignSubVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberRelationFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignLogoVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignQueryVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignRegisterQueryVO;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.order.api.model.vo.response.PayChannelParameterFeignDetailVO;
import com.ssy.lingxi.order.api.model.vo.response.PaymentParameterFeignDetailVO;
import com.ssy.lingxi.pay.common.*;
import com.ssy.lingxi.pay.constant.Constants;
import com.ssy.lingxi.pay.entity.*;
import com.ssy.lingxi.pay.model.vo.request.*;
import com.ssy.lingxi.pay.model.vo.response.*;
import com.ssy.lingxi.pay.repository.*;
import com.ssy.lingxi.pay.service.*;
import com.ssy.lingxi.pay.utils.CreditUtil;
import com.ssy.lingxi.report.api.enums.CreditOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.workflow.api.model.contant.ProcessEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.InternalProcessQueryVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskStartVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleProcessDefVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 授信申请接口实现
 * @author 伍将
 * @date 2020/8/15 10:01
 * @version 2.0.0
 */
@Service
public class CreditApplyServiceImpl implements ICreditApplyService {


    @Resource
    private CreditApplyRepository applyRepository;

    @Resource
    private CreditRepository creditRepository;

    @Resource
    private CreditOuterVerifyRecordRepository outerVerifyRecordRepository;

    @Resource
    private CreditInnerVerifyRecordRepository innerVerifyRecordRepository;

    @Resource
    MemberInnerControllerFeign memberInnerControllerFeign;

    @Resource
    private ICreditVerifyService verifyService;

    @Resource
    private CreditVerifyRepository verifyRepository;

    @Resource
    private ICreditOuterVerifyRecordService outerVerifyRecordService;

    @Resource
    private ICreditInnerVerifyRecordService innerVerifyRecordService;

    @Resource
    private CreditBillRepository billRepository;

    @Resource
    private IFeignService feignService;
    /**
     * 工作流接口
     */
    @Resource
    private IProcessFeignService processFeign;

    /**
     * 获取申请单
     * @author 伍将
     * @date 2020/8/20
     * @param user: 
     * @param pageVO: 
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditApplyPageQueryVO>> pageApplyByLower(UserLoginCacheDTO user, PageQueryCreditApplyVO pageVO) {
        // 查询所有数据时，不需要额外增加内外部状态限制
        return pageApplyByLower(user, pageVO, null);
    }

    /**
     * 获当前待提交申请
     * @author 伍将
     * @date 2020/8/20
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditApplyPageQueryVO>> pageWaitSubmitApplyByLower(UserLoginCacheDTO user, PageQueryCreditApplyVO pageVO) {
        // 查询待提交数据时，外部状态为不接受申请或内部状态为未提交
        List<Integer> outerStatusList = new ArrayList<>();
        outerStatusList.add(CreditApplyOuterStatusEnum.REFUSE_APPLY.getCode());
        outerStatusList.add(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode());

        return pageApplyByLower(user, pageVO, outerStatusList);
    }

    /**
     * 下级会员获取申请单
     * @author 伍将
     * @date 2020/8/20
     * @param user:
     * @param pageVO:
     * @param outerStatusList:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditApplyPageQueryVO>>
     **/
    private Wrapper<PageData<CreditApplyPageQueryVO>> pageApplyByLower(UserLoginCacheDTO user, PageQueryCreditApplyVO pageVO, List<Integer> outerStatusList) {

        // 查询会员信息
        MemberFeignVO memberFeignVO = new MemberFeignVO();
        memberFeignVO.setMemberId(user.getMemberId());
        memberFeignVO.setRoleId(user.getMemberRoleId());
        Wrapper<List<MemberFeignQueryVO>> listWrapper = memberInnerControllerFeign.listUpperMembers(memberFeignVO);
        if(listWrapper==null){
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(listWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(listWrapper);
        }

        // step 1: 组装查询条件
        Specification<CreditApplyDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 默认查询未删除状态
            list.add(criteriaBuilder.equal(root.get("isDelete").as(Long.class), CommonBooleanEnum.NO.getCode()));
//            // 默认查询当前申请状态
//            list.add(criteriaBuilder.equal(root.get("isCurrent").as(Integer.class), CommonBooleanEnum.YES.getCode()));
            // 只查询外部申请
//            list.add(criteriaBuilder.equal(root.get("applyType").as(Integer.class), CreditApplyTypeEnum.OUTER.getCode()));
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));

            if (null != pageVO.getOuterStatus()
                    && !CreditApplyOuterStatusEnum.ALL.getCode().equals(pageVO.getOuterStatus())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (null != pageVO.getInnerStatus()
                    && !CreditApplyLowerInnerStatusEnum.ALL.getCode().equals(pageVO.getInnerStatus())) {
                list.add(criteriaBuilder.equal(root.get("lowerInnerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (outerStatusList != null && outerStatusList.size() > 0) {
                list.add(criteriaBuilder.in(root.get("outerStatus")).value(outerStatusList));
            }
            // 筛选上级会员名称
            if (StringUtils.hasLength(pageVO.getMemberName())) {
                List<Long> idList = new ArrayList<>();
                for (MemberFeignQueryVO r : listWrapper.getData()) {
                    if (r.getMemberName().contains(pageVO.getMemberName())) {
                        Long memberId = r.getMemberId();
                        idList.add(memberId);
                    }
                }
                list.add(criteriaBuilder.in(root.get("parentMemberId")).value(idList));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());

        // step 3: 分页查询数据
        Page<CreditApplyDO> result = this.applyRepository.findAll(spec, page);


        // step 4: 组装返回数据
        List<CreditApplyPageQueryVO> resultList = result.getContent().stream().map(r -> {
            CreditApplyPageQueryVO queryVO = new CreditApplyPageQueryVO();
            queryVO.setCreditId(r.getCreditId());
            queryVO.setId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            MemberFeignQueryVO memberFeignQueryVO = listWrapper.getData().stream().filter(item ->
                    item.getMemberId().equals(r.getParentMemberId())
                            && item.getRoleId().equals(r.getParentMemberRoleId())).findFirst().orElse(null);
            if (memberFeignQueryVO != null) {
                queryVO.setParentMemberName(memberFeignQueryVO.getMemberName());
                queryVO.setMemberTypeName(memberFeignQueryVO.getMemberTypeName());
                queryVO.setMemberRoleName(memberFeignQueryVO.getRoleName());
                queryVO.setMemberLevelName(memberFeignQueryVO.getLevelTag());
                queryVO.setLogo(memberFeignQueryVO.getLogo());
            }
            queryVO.setOriginalQuota(r.getOriginalQuota());
            queryVO.setApplyQuota(r.getApplyQuota());
            queryVO.setInnerStatus(r.getLowerInnerStatus());
            queryVO.setInnerStatusName(CreditApplyLowerInnerStatusEnum.getItemMessage(r.getLowerInnerStatus()));
            queryVO.setOuterStatus(r.getOuterStatus());
            queryVO.setOuterStatusName(CreditApplyOuterStatusEnum.getItemMessage(r.getOuterStatus()));
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 新增授信申请
     * @author 伍将
     * @date 2020/8/18
     * @param addVO:
     * @return com.ssy.lingxi.common.response.Wrapper<java.lang.Long>
     **/
    @Override
    @Transactional
    public Wrapper<Long> add(UserLoginCacheDTO user, CreditApplyAddVO addVO) {
        return AddOrUpdateApply(user, addVO, CreditApplyTypeEnum.OUTER);
    }

    /**
     * 授信调额
     * @author 伍将
     * @date 2020/8/29
     * @param user:
     * @param adjustQuotaVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    @Transactional
    public Wrapper<Long> adjustQuota(UserLoginCacheDTO user, CreditAdjustQuotaVO adjustQuotaVO) {

        CreditApplyAddVO addVO = new CreditApplyAddVO();
        addVO.setCreditId(adjustQuotaVO.getCreditId());
        addVO.setApplyId(0L);
        addVO.setApplyQuota(Constants.PAY_CREDIT_DEFAULT_Quota);
        addVO.setBillDay(Constants.PAY_CREDIT_DEFAULT_BILL_DAY);
        addVO.setRepayPeriod(Constants.PAY_CREDIT_DEFAULT_BILL_REPAY_PERIOD);

        //  验证数据
        CreditDO creditDO = creditRepository.findById(adjustQuotaVO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }
        PaymentParameterFeignDetailVO payParameters = feignService.getCreditPayment(creditDO.getParentMemberId(), creditDO.getParentMemberRoleId());
        if (payParameters != null) {
            //上调额度
            PayChannelParameterFeignDetailVO detailVO = payParameters.getParameters().stream().filter(p -> p.getParameter().equals(OrderPaymentParameterEnum.CREDIT_QUOTA_INCREAMENT) && StringUtils.hasLength(p.getValue())).findFirst().orElse(null);
            double increment = detailVO == null ? 0D : Double.parseDouble(detailVO.getValue());
            if (creditDO.getQuota() > 0) {
                // 如果原有额度大于0，申请额度自动上调
                addVO.setApplyQuota(creditDO.getQuota() * (100 + increment) / 100);
            } else {
                addVO.setApplyQuota(increment);
            }
        }

        return AddOrUpdateApply(user, addVO, CreditApplyTypeEnum.INNER);
    }

    /**
     * 新增或修改授信申请
     * @author 伍将
     * @date 2020/8/29
     * @param addVO:
     * @param applyTypeEnum:
     * @return com.ssy.lingxi.common.response.Wrapper<java.lang.Long>
     **/
    private Wrapper<Long> AddOrUpdateApply(UserLoginCacheDTO user, CreditApplyAddVO addVO, CreditApplyTypeEnum applyTypeEnum) {

        // step 1: 验证数据
        CreditDO creditDO = creditRepository.findById(addVO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }
        // 账号日不能大于28日
        if (addVO.getBillDay() > Constants.PAY_CREDIT_MAX_BILL_DAY) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_BILL_DAY_ERROR);
        }

        CreditApplyDO applyDO;
        // 更新检查
        if (addVO.getApplyId() > 0) {
            CreditApplyDO oldApplyDO = applyRepository.findById(addVO.getApplyId()).orElse(null);
            if (oldApplyDO == null) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
            }

            // 已删除的数据不允许修改
            if (CommonBooleanEnum.YES.getCode().equals(oldApplyDO.getIsDelete())) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
            }

            // 非当前正在申请的数据不允许修改
            if (!CommonBooleanEnum.YES.getCode().equals(oldApplyDO.getIsCurrent())) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_UPDATE);
            }

            // 外部状态为：待提交或不接受申请才允许修改
            if (!CreditApplyOuterStatusEnum.REFUSE_APPLY.getCode().equals(oldApplyDO.getOuterStatus())
                    && !CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode().equals(oldApplyDO.getOuterStatus())) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_UPDATE);
            }

            // 组装DO对象
            oldApplyDO.setLowerInnerStatus(CreditApplyLowerInnerStatusEnum.WAIT_SUBMIT.getCode());
            oldApplyDO.setSuperiorInnerStatus(CreditApplySuperiorInnerStatusEnum.WAIT_SUBMIT.getCode());
            oldApplyDO.setOuterStatus(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode());
            applyDO = oldApplyDO;
            applyDO.setFileList(addVO.getFileList());
            applyDO.setOriginalQuota(creditDO.getQuota());
            applyDO.setApplyQuota(addVO.getApplyQuota());
            applyDO.setBillDay(addVO.getBillDay());
            applyDO.setRepayPeriod(addVO.getRepayPeriod());
        }
        // 新增检查
        else {
            // 检查是否重复申请
            CreditApplyDO oldApplyDO = applyRepository.findByIsCurrentAndCreditIdAndIsDelete(CommonBooleanEnum.YES.getCode(), creditDO.getId(), CommonBooleanEnum.NO.getCode());
            if (oldApplyDO != null) {

                // 旧申请外部状态为接受申请时，验证是否满足申请间隔时间
                if (CreditApplyOuterStatusEnum.ACCEPT_APPLY.getCode().equals(oldApplyDO.getOuterStatus())) {
                    // 验证满多少天后可调额申请
                    PaymentParameterFeignDetailVO payParameters = feignService.getCreditPayment(oldApplyDO.getParentMemberId(), oldApplyDO.getParentMemberRoleId());
                    if (payParameters == null || CollectionUtils.isEmpty(payParameters.getParameters()) || payParameters.getParameters().stream().noneMatch(paramter -> paramter.getParameter().equals(OrderPaymentParameterEnum.CREDIT_DAYS))) {
                        throw new BusinessException(ResponseCode.PAY_CREDIT_CONFIG_NO_OPEN);
                    }

                    // 获取允许申请的间隔天数
                    PayChannelParameterFeignDetailVO detailVO = payParameters.getParameters().stream().filter(parameter -> parameter.getParameter().equals(OrderPaymentParameterEnum.CREDIT_DAYS) && StringUtils.hasLength(parameter.getValue())).findFirst().orElse(null);
                    long intervalDay = detailVO == null ? 0L : Long.parseLong(detailVO.getValue());
                    long betweenDay = DateUtil.between(
                            DateUtil.date(oldApplyDO.getApplyTime()),
                            DateUtil.date(System.currentTimeMillis()),
                            DateUnit.DAY);
                    // 间隔时间小于等配置时间则不允许再次申请
                    if (betweenDay < intervalDay) {
                        throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_TIME_ERROR);
                    }
                }
                // 已存在待提交/待确认申请时，不允许重复提交
                else if (CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode().equals(oldApplyDO.getOuterStatus())
                        || CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode().equals(oldApplyDO.getOuterStatus())) {
                    throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_EXIST);
                }

                // 如果旧申请为接受申请，则更改为非当前申请，并重新新建申请
                if (CreditApplyOuterStatusEnum.ACCEPT_APPLY.getCode().equals(oldApplyDO.getOuterStatus())) {
                    oldApplyDO.setIsCurrent(CommonBooleanEnum.NO.getCode());
                    oldApplyDO.setUpdateTime(System.currentTimeMillis());
                    applyRepository.saveAndFlush(oldApplyDO);
                    applyDO = convertApplyDO(addVO, creditDO, applyTypeEnum);
                } else {
                    // 组装DO对象
                    oldApplyDO.setLowerInnerStatus(CreditApplyLowerInnerStatusEnum.WAIT_SUBMIT.getCode());
                    oldApplyDO.setSuperiorInnerStatus(CreditApplySuperiorInnerStatusEnum.WAIT_SUBMIT.getCode());
                    oldApplyDO.setOuterStatus(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode());
                    applyDO = oldApplyDO;
                    applyDO.setOriginalQuota(creditDO.getQuota());
                    applyDO.setApplyQuota(addVO.getApplyQuota());
                    applyDO.setBillDay(addVO.getBillDay());
                    applyDO.setRepayPeriod(addVO.getRepayPeriod());
                }
            }
            // 没有查询到旧申请，则直接组装一个
            else {
                // 组装DO对象
                applyDO = convertApplyDO(addVO, creditDO, applyTypeEnum);
            }
        }

        // 保存申请
        applyRepository.saveAndFlush(applyDO);


        // 更新授信信息
        creditDO.setStatus(CreditStatusEnum.APPLY.getCode());
        creditDO.setIsHasApply(CommonBooleanEnum.YES.getCode());
        creditDO.setUpdateTime(System.currentTimeMillis());
        creditRepository.saveAndFlush(creditDO);

        // 如果申请类型为内部，自动提交到内部状态
        if (applyTypeEnum == CreditApplyTypeEnum.INNER) {
            Wrapper<Void> wrapper = submitApplyToInner(user, applyDO, creditDO);
            if (wrapper == null || wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_SUBMIT_ERROR);
            }
        }

        // 更新授信信息
        creditDO.setStatus(CreditStatusEnum.APPLY.getCode());
        creditDO.setIsHasApply(CommonBooleanEnum.YES.getCode());
        creditDO.setUpdateTime(System.currentTimeMillis());
        creditRepository.saveAndFlush(creditDO);

        return Wrapper.success(applyDO.getId());
    }

    /**
     * 组装申请Do对象
     * @author 伍将
     * @date 2020/8/29
     * @param addVO:
     * @param creditDO:
     * @param applyTypeEnum:
     * @return com.ssy.lingxi.pay.entity.CreditApplyDO
     **/
    private CreditApplyDO convertApplyDO(CreditApplyAddVO addVO, CreditDO creditDO, CreditApplyTypeEnum applyTypeEnum) {
        CreditApplyDO applyDO = new CreditApplyDO();
        applyDO.setCreditId(addVO.getCreditId());
        applyDO.setMemberId(creditDO.getMemberId());
        applyDO.setRoleId(creditDO.getMemberRoleId());
        applyDO.setParentMemberId(creditDO.getParentMemberId());
        applyDO.setParentMemberRoleId(creditDO.getParentMemberRoleId());
        String appNo = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        applyDO.setApplyNo(appNo);
        applyDO.setOriginalQuota(creditDO.getQuota());
        applyDO.setApplyQuota(addVO.getApplyQuota());
        applyDO.setAuditQuota(addVO.getApplyQuota());
        applyDO.setIsCurrent(CommonBooleanEnum.YES.getCode());
        applyDO.setApplyType(applyTypeEnum.getCode());
        applyDO.setOuterStatus(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode());
        applyDO.setLowerInnerStatus(CreditApplyLowerInnerStatusEnum.WAIT_SUBMIT.getCode());
        applyDO.setSuperiorInnerStatus(CreditApplySuperiorInnerStatusEnum.WAIT_SUBMIT.getCode());
        applyDO.setApplyTime(System.currentTimeMillis());
        applyDO.setBillDay(addVO.getBillDay());
        applyDO.setRepayPeriod(addVO.getRepayPeriod());
        applyDO.setCreateTime(System.currentTimeMillis());
        applyDO.setUpdateTime(0L);
        applyDO.setOuterTaskId("");
        applyDO.setOuterTaskType(0);
        applyDO.setInnerTaskId("");
        applyDO.setInnerTaskType(ProcessEnum.PAY_CREDIT_APPLY_VERIFY.getCode());
        applyDO.setIsDelete(CommonBooleanEnum.NO.getCode());
        applyDO.setFileList(addVO.getFileList());

        return applyDO;
    }

    /**
     * 提交授信申请
     * @author 伍将
     * @date 2020/8/19
     * @param submitVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    @Transactional
    public Wrapper<Void> submit(UserLoginCacheDTO user, CreditApplySubmitVO submitVO) {

        CreditApplyDO applyDO = applyRepository.findById(submitVO.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 非待提交状态不允许修改数据
        if (!applyDO.getOuterStatus().equals(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_SUBMIT);
        }
        // 非当前正在申请的数据不允许修改
        if (!applyDO.getIsCurrent().equals(CommonBooleanEnum.YES.getCode())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_SUBMIT);
        }
        // 所属授信必须存在
        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        return submitApplyToInner(user, applyDO, creditDO);
    }

    /**
     *  提交申请到内部
     * @author 伍将
     * @date 2020/8/29
     * @param user:
     * @param applyDO:
     * @param creditDO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    public Wrapper<Void> submitApplyToInner(UserLoginCacheDTO user, CreditApplyDO applyDO, CreditDO creditDO) {

        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 非待提交状态不允许修改数据
        if (!CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode().equals(applyDO.getOuterStatus())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_SUBMIT);
        }
        // 非当前正在申请的数据不允许修改
        if (!CommonBooleanEnum.YES.getCode().equals(applyDO.getIsCurrent())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_SUBMIT);
        }
        // 所属授信必须存在
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 授信申请单审核流转
        TaskStartVO taskStartVO=new TaskStartVO();
        taskStartVO.setMemberId(creditDO.getMemberId());
        taskStartVO.setRoleId(creditDO.getMemberRoleId());
        taskStartVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
        taskStartVO.setDataId(applyDO.getId());
        Wrapper<SimpleTaskCompleteVO> processResultVOWrapper = processFeign.startSimpleProcess(taskStartVO);
        if (ResponseCode.SUCCESS.getCode() == processResultVOWrapper.getCode()) {
            applyDO.setOuterStatus(CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode());
            applyDO.setLowerInnerStatus(CreditApplyLowerInnerStatusEnum.SUBMIT.getCode());
            applyDO.setInnerTaskId(processResultVOWrapper.getData().getTaskId());
            applyDO.setInnerTaskStep(processResultVOWrapper.getData().getStep());
            applyDO.setSuperiorInnerStatus(processResultVOWrapper.getData().getStatus());
            applyDO.setUpdateTime(System.currentTimeMillis());
            applyDO.setApplyTime(System.currentTimeMillis());
            // 授信处理待提交审核授信申请单+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(applyDO.getParentMemberId());
            noticeVO.setRoleId(applyDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.CREDIT.getCode());
            noticeVO.setIncreaseOperateType(CreditOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            feignService.addSysOperateNotice(noticeVO);

            applyRepository.saveAndFlush(applyDO);
            // 新增外部流转记录
            if (CreditApplyTypeEnum.OUTER.getCode().equals(applyDO.getApplyType())) {
                addCreditOuterVerifyRecord(applyDO, user, "");
            }

            // 更新授信信息
            creditDO.setIsHasApply(CommonBooleanEnum.YES.getCode());
            creditDO.setStatus(CreditStatusEnum.APPLY.getCode());
            creditDO.setUpdateTime(System.currentTimeMillis());
            creditRepository.saveAndFlush(creditDO);

            // 新增待提交审核授信申请单消息通知
            MemberRelationFeignVO feignVO = new MemberRelationFeignVO();
            feignVO.setUpperMemberId(applyDO.getParentMemberId());
            feignVO.setUpperRoleId(applyDO.getParentMemberRoleId());
            feignVO.setMemberId(applyDO.getMemberId());
            feignVO.setRoleId(applyDO.getRoleId());
            Wrapper<MemberFeignQueryVO> memberWrapper = memberInnerControllerFeign.getMemberInfo(feignVO);
            if (null != memberWrapper && memberWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != memberWrapper.getData()) {
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(applyDO.getParentMemberId());
                request.setRoleId(applyDO.getParentMemberRoleId());
                request.setMessageNotice(MessageTemplateCode.credit_handle_wait_submit);
                List<String> params = new ArrayList<>();
                params.add(memberWrapper.getData().getMemberName());
                params.add(applyDO.getApplyNo());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        } else {
            return Wrapper.fail(processResultVOWrapper);
        }

        return Wrapper.success();
    }

    /**
     * 新增外部流转记录
     * @author 伍将
     * @date 2020/8/20
     * @param applyDO:
     * @param user:
     * @param opinion:
     * @return void
     **/
    private void addCreditOuterVerifyRecord(CreditApplyDO applyDO, UserLoginCacheDTO user, String opinion) {
        CreditOuterVerifyRecordDO outerVerifyRecordDO = new CreditOuterVerifyRecordDO();
        outerVerifyRecordDO.setCreditId(applyDO.getCreditId());
        outerVerifyRecordDO.setApplyId(applyDO.getId());
        outerVerifyRecordDO.setUserId(user.getUserId());
        outerVerifyRecordDO.setMemberId(user.getMemberId());
        outerVerifyRecordDO.setRoleId(user.getMemberRoleId());
        outerVerifyRecordDO.setRoleName(user.getMemberRoleName());
        outerVerifyRecordDO.setStatus(applyDO.getOuterStatus());
        outerVerifyRecordDO.setOperate(CreditApplyOuterStatusEnum.getItemRemark(applyDO.getOuterStatus()));
        outerVerifyRecordDO.setOperateTime(System.currentTimeMillis());
        outerVerifyRecordDO.setOpinion(opinion);
        outerVerifyRecordRepository.saveAndFlush(outerVerifyRecordDO);
    }

    /**
     * 提交审核授信申请
     * @author 伍将
     * @date 2020/8/19
     * @param submitVerifyVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    @Transactional
    public Wrapper<Void> submitVerify(UserLoginCacheDTO user, CreditApplyVerifyVO submitVerifyVO) {

        CreditApplyDO applyDO = applyRepository.findById(submitVerifyVO.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 非待提交状态不允许修改数据
        if (!CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode().equals(applyDO.getOuterStatus())
                || !CreditApplySuperiorInnerStatusEnum.WAIT_SUBMIT.getCode().equals(applyDO.getSuperiorInnerStatus())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_SUBMIT_VERIFY);
        }
        // 所属授信必须存在
        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 查询审批信息，没有则新增
        CreditVerifyDO verifyDO = verifyRepository.findByApplyId(submitVerifyVO.getApplyId());
        if (verifyDO == null) {
            verifyDO = new CreditVerifyDO();
            verifyDO.setApplyId(applyDO.getId());
            verifyDO.setQuota(applyDO.getApplyQuota());
            verifyDO.setBillDay(applyDO.getBillDay());
            verifyDO.setRepayPeriod(applyDO.getRepayPeriod());
        }
        verifyDO.setVerifyTime(System.currentTimeMillis());
        verifyRepository.saveAndFlush(verifyDO);

        // 授信申请单审核流转
        TaskExecuteVO taskExecuteVO=new TaskExecuteVO();
        taskExecuteVO.setMemberId(creditDO.getMemberId());
        taskExecuteVO.setRoleId(creditDO.getMemberRoleId());
        taskExecuteVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
        taskExecuteVO.setTaskId(applyDO.getInnerTaskId());
        taskExecuteVO.setAgree(submitVerifyVO.getIsPass());
        taskExecuteVO.setDataId(applyDO.getId());
        Wrapper<SimpleTaskCompleteVO> taskCompleteVOWrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (null == taskCompleteVOWrapper || ResponseCode.SUCCESS.getCode() != taskCompleteVOWrapper.getCode()
                || null == taskCompleteVOWrapper.getData()) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_WORKFLOW_ERROR);
        } else {
            applyDO.setSuperiorInnerStatus(taskCompleteVOWrapper.getData().getStatus());
            applyDO.setInnerTaskId(taskCompleteVOWrapper.getData().getTaskId());
            applyDO.setInnerTaskStep(taskCompleteVOWrapper.getData().getStep());
            applyDO.setUpdateTime(System.currentTimeMillis());
            applyRepository.saveAndFlush(applyDO);

            // 新增内部流转记录
            addCreditInnerVerifyRecord(applyDO, user, submitVerifyVO.getOpinion(), applyDO.getInnerTaskStep(), CreditApplySuperiorActionEnum.getItemMessage(applyDO.getInnerTaskStep()));

            // 授信处理待提交审核授信申请单-1,待审核授信申请单（一级）/待确认授信申请单+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(applyDO.getParentMemberId());
            noticeVO.setRoleId(applyDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.CREDIT.getCode());
            CreditOperateTypeEnum typeEnum = (CreditApplySuperiorInnerStatusEnum.SUBMIT_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus()) ? CreditOperateTypeEnum.TO_BE_VALIFY_STEP1 : CreditOperateTypeEnum.TO_BE_CONFIRM);
            noticeVO.setIncreaseOperateType(typeEnum.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceOperateType(CreditOperateTypeEnum.TO_BE_VALIFY_COMMIT.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            feignService.addSysOperateNotice(noticeVO);

            // 新增待审核授信申请单（一级）/待确认授信申请单消息通知
            MemberRelationFeignVO feignVO = new MemberRelationFeignVO();
            feignVO.setUpperMemberId(applyDO.getParentMemberId());
            feignVO.setUpperRoleId(applyDO.getParentMemberRoleId());
            feignVO.setMemberId(applyDO.getMemberId());
            feignVO.setRoleId(applyDO.getRoleId());
            Wrapper<MemberFeignQueryVO> memberWrapper = memberInnerControllerFeign.getMemberInfo(feignVO);
            if (null != memberWrapper && memberWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != memberWrapper.getData()) {
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(applyDO.getParentMemberId());
                request.setRoleId(applyDO.getParentMemberRoleId());
                String messageTemplateCode = (CreditApplySuperiorInnerStatusEnum.SUBMIT_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())
                        ? MessageTemplateCode.credit_handle_audit_1 : MessageTemplateCode.credit_handle_submit);
                request.setMessageNotice(messageTemplateCode);
                List<String> params = new ArrayList<>();
                params.add(memberWrapper.getData().getMemberName());
                params.add(applyDO.getApplyNo());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        }

        return Wrapper.success();
    }

    /**
     * 新增内部流转记录
     * @author 伍将
     * @date 2020/8/20
     * @param applyDO: 授信申请
     * @param user: 当前用户
     * @param opinion: 意见
     * @param taskStep 步骤
     * @return void
     **/
    private void addCreditInnerVerifyRecord(CreditApplyDO applyDO, UserLoginCacheDTO user, String opinion, Integer taskStep, String operate) {
        CreditInnerVerifyRecordDO innerVerifyRecordDO = new CreditInnerVerifyRecordDO();
        innerVerifyRecordDO.setStep(taskStep);
        innerVerifyRecordDO.setCreditId(applyDO.getCreditId());
        innerVerifyRecordDO.setApplyId(applyDO.getId());
        innerVerifyRecordDO.setUserId(user.getUserId());
        innerVerifyRecordDO.setMemberId(user.getMemberId());
        innerVerifyRecordDO.setRoleId(user.getMemberRoleId());
        innerVerifyRecordDO.setOperator(user.getUserName());
        innerVerifyRecordDO.setDepartment(user.getUserOrgName());
        innerVerifyRecordDO.setJobTitle(user.getUserJobTitle());
        innerVerifyRecordDO.setStatus(applyDO.getSuperiorInnerStatus());
        innerVerifyRecordDO.setOperate(operate);
        innerVerifyRecordDO.setOperateTime(System.currentTimeMillis());
        innerVerifyRecordDO.setOpinion(opinion);
        innerVerifyRecordRepository.saveAndFlush(innerVerifyRecordDO);
    }

    /**
     * 确认审核授信申请
     * @author 伍将
     * @date 2020/8/20
     * @param user:
     * @param verifyVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    @Transactional
    public Wrapper<Void> confirmVerify(UserLoginCacheDTO user, CreditApplyVerifyVO verifyVO) {

        CreditApplyDO applyDO = applyRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 外部状态不等于待确认，内部状态不等于（提交审核失败/一级审核失败/二级审核失败/三级审核失败/三级审核成功），不允许待确认审核
        if (!CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode().equals(applyDO.getOuterStatus())
                || (!CreditApplySuperiorInnerStatusEnum.SUBMIT_VERIFY_FAIL.getCode().equals(applyDO.getSuperiorInnerStatus())
                && !CreditApplySuperiorInnerStatusEnum.STEP1_VERIFY_FAIL.getCode().equals(applyDO.getSuperiorInnerStatus())
                && !CreditApplySuperiorInnerStatusEnum.STEP2_VERIFY_FAIL.getCode().equals(applyDO.getSuperiorInnerStatus())
                && !CreditApplySuperiorInnerStatusEnum.STEP3_VERIFY_FAIL.getCode().equals(applyDO.getSuperiorInnerStatus())
                && !CreditApplySuperiorInnerStatusEnum.STEP3_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus()))
        ) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_UN_ALLOW_VERIFY_ACCEPT);
        }

        // 当前内部状态不等于三级审核通过时，不允许接受申请
        if (CommonBooleanEnum.YES.getCode().equals(verifyVO.getIsPass())
                && !CreditApplySuperiorInnerStatusEnum.STEP3_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_UN_ALLOW_VERIFY_ACCEPT);
        }

        // 所属授信必须存在
        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        TaskExecuteVO taskExecuteVO=new TaskExecuteVO();
        taskExecuteVO.setMemberId(creditDO.getMemberId());
        taskExecuteVO.setRoleId(creditDO.getMemberRoleId());
        taskExecuteVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
        taskExecuteVO.setTaskId(applyDO.getInnerTaskId());
        taskExecuteVO.setAgree(verifyVO.getIsPass());
        taskExecuteVO.setDataId(applyDO.getId());
        Wrapper<SimpleTaskCompleteVO> taskResultVOWrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == taskResultVOWrapper.getCode()) {
            applyDO.setSuperiorInnerStatus(taskResultVOWrapper.getData().getStatus());
            applyDO.setInnerTaskId(taskResultVOWrapper.getData().getTaskId());
            applyDO.setInnerTaskStep(taskResultVOWrapper.getData().getStep());
            if (CreditApplySuperiorInnerStatusEnum.VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())) {
                applyDO.setOuterStatus(CreditApplyOuterStatusEnum.ACCEPT_APPLY.getCode());
            } else if (CreditApplySuperiorInnerStatusEnum.VERIFY_FAIL.getCode().equals(applyDO.getSuperiorInnerStatus())) {
                applyDO.setOuterStatus(CreditApplyOuterStatusEnum.REFUSE_APPLY.getCode());
            }
            applyDO.setUpdateTime(System.currentTimeMillis());
            applyRepository.saveAndFlush(applyDO);

            // 新增内部流转记录
            addCreditInnerVerifyRecord(applyDO, user, verifyVO.getOpinion(), applyDO.getInnerTaskStep(), CreditApplySuperiorActionEnum.getItemMessage(applyDO.getInnerTaskStep()));

            // 新增外部流转记录
            if (CreditApplyTypeEnum.OUTER.getCode().equals(applyDO.getApplyType())) {
                addCreditOuterVerifyRecord(applyDO, user, verifyVO.getOpinion());
            }

            // 授信处理待确认授信申请单-1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(applyDO.getParentMemberId());
            noticeVO.setRoleId(applyDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.CREDIT.getCode());
            noticeVO.setReduceOperateType(CreditOperateTypeEnum.TO_BE_CONFIRM.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            feignService.addSysOperateNotice(noticeVO);

            // 审核通过时，修改授信信息
            if (CreditApplyOuterStatusEnum.ACCEPT_APPLY.getCode().equals(applyDO.getOuterStatus())) {
                Double quota = applyDO.getApplyQuota();
                Integer billDay = applyDO.getBillDay();
                Integer repayPeriod = applyDO.getRepayPeriod();

                // 查询授信申请审核
                Wrapper<CreditVerifyVO> verifyDOWrapper = verifyService.getVerify(applyDO.getId());
                if(verifyDOWrapper==null){
                    return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
                }else if(verifyDOWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
                    return Wrapper.fail(verifyDOWrapper);
                }

                // 如果存在审批结果，则替换审批的数值
                if (verifyDOWrapper.getData() != null) {
                    quota = verifyDOWrapper.getData().getQuota();
                    billDay = verifyDOWrapper.getData().getBillDay();
                    repayPeriod = verifyDOWrapper.getData().getRepayPeriod();
                }

                creditDO.setQuota(quota);
                creditDO.setBillDay(billDay);
                creditDO.setRepayPeriod(repayPeriod);
                // 如果授信状态为冻结则保持冻结状态，反之调整为正常状态
                creditDO.setStatus(CreditStatusEnum.FROZEN.getCode().equals(creditDO.getStatus()) ? creditDO.getStatus() : CreditStatusEnum.THAW.getCode());
                creditDO.setUpdateTime(System.currentTimeMillis());
                // 申请审核通过后，设置授信当前为可用
                creditDO.setIsUsable(CommonBooleanEnum.YES.getCode());
                creditRepository.saveAndFlush(creditDO);

                int nowDay = DateUtil.date().dayOfMonth();
                long billBelongTime;
                // 当前天大于等于账单日，则账单所属时间为当月
                if (nowDay >= billDay) {
                    billBelongTime = DateUtil.beginOfMonth(DateUtil.date()).getTime();
                }
                // 否则账单所属时间为前一月
                else {
                    billBelongTime = DateUtil.offsetMonth(DateUtil.beginOfMonth(DateUtil.date()), -1).getTime();
                }
                // 查询是否存在对应月份账单，存在则更新，不存在则新增
                CreditBillDO billDO = billRepository.findByBillBelongTimeAndCreditId(billBelongTime, creditDO.getId());
                if (billDO == null) {
                    billDO = new CreditBillDO();
                    billDO.setCreditId(creditDO.getId());
                    billDO.setBillBelongTime(billBelongTime);
                } else {
                    billDO.setUpdateTime(System.currentTimeMillis());
                }
                billDO.setBillDay(creditDO.getBillDay());
                billDO.setRepayPeriod(creditDO.getRepayPeriod());
                Date expireTime = CreditUtil.getExpireTime(DateUtil.date(billBelongTime), billDay, repayPeriod);
                billDO.setExpireTime(expireTime.getTime());
                billRepository.saveAndFlush(billDO);
            }

            // 新增确认授信申请单后消息消息通知
            MemberFeignIdVO feignVO = new MemberFeignIdVO();
            feignVO.setMemberId(applyDO.getParentMemberId());
            Wrapper<MemberFeignRegisterQueryVO> memberWrapper = memberInnerControllerFeign.getMemberRegisterInfo(feignVO);
            if (null != memberWrapper && memberWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != memberWrapper.getData()) {
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(applyDO.getMemberId());
                request.setRoleId(applyDO.getRoleId());
                request.setMessageNotice(MessageTemplateCode.credit_apply);
                List<String> params = new ArrayList<>();
                params.add(applyDO.getApplyNo());
                params.add(memberWrapper.getData().getName());
                params.add(CreditApplyOuterStatusEnum.getItemMessage(applyDO.getOuterStatus()));
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        } else {
            return Wrapper.fail(taskResultVOWrapper);
        }

        return Wrapper.success();
    }

    /**
     * 删除授信申请
     * @author 伍将
     * @date 2020/8/20
     * @param user:
     * @param vo:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> delete(UserLoginCacheDTO user, CreditApplySubmitVO vo) {

        CreditApplyDO applyDO = applyRepository.findById(vo.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        if (CommonBooleanEnum.YES.getCode().equals(applyDO.getIsDelete())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        if (!applyDO.getOuterStatus().equals(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_DELETE);
        }

        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 不进行物理删除，更改标记字段，查询数据时需增加验证条件
        applyDO.setIsDelete(CommonBooleanEnum.YES.getCode());
        applyDO.setUpdateTime(System.currentTimeMillis());
        applyRepository.saveAndFlush(applyDO);
        // 还原授信状态，如果当前为申请中则还原成正常，其他状态不变
        if (CreditStatusEnum.APPLY.getCode().equals(creditDO.getStatus())) {
            creditDO.setStatus(CreditStatusEnum.THAW.getCode());
        }
        creditDO.setUpdateTime(System.currentTimeMillis());
        creditRepository.saveAndFlush(creditDO);


        return Wrapper.success();
    }

    /**
     * 构建流转步骤
     * @param step
     * @param taskName
     * @param roleName
     * @param isExecute
     * @return
     */
    private CreditApplyTaskStepVO buildCreditApplyTaskStepVO(Integer step,String taskName,String roleName,Integer isExecute){
        CreditApplyTaskStepVO outerTaskStepVO = new CreditApplyTaskStepVO();
        outerTaskStepVO.setStep(step);
        outerTaskStepVO.setTaskName(taskName);
        outerTaskStepVO.setRoleName(roleName);
        outerTaskStepVO.setIsExecute(isExecute);
        return outerTaskStepVO;
    }

    /**
     * 获取授信申请详情
     * @author 伍将
     * @date 2020/8/18
     * @param getDetailVO
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.pay.model.vo.response.CreditApplyDetailVO>
     **/
    @Override
    public Wrapper<CreditApplyDetailVO> getDetail(UserLoginCacheDTO user, CreditApplyGetDetailVO getDetailVO, Boolean isUpperSle) {

        // 获取授信申请信息
        CreditDO creditDo = creditRepository.findById(getDetailVO.getCreditId()).orElse(null);
        if (creditDo == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 组装数据
        CreditApplyDetailVO result = new CreditApplyDetailVO();

        // 查询会员信息
        MemberRelationFeignVO memberRelationFeignVO = new MemberRelationFeignVO();
        memberRelationFeignVO.setMemberId(creditDo.getMemberId());
        memberRelationFeignVO.setRoleId(creditDo.getMemberRoleId());
        memberRelationFeignVO.setUpperMemberId(creditDo.getParentMemberId());
        memberRelationFeignVO.setUpperRoleId(creditDo.getParentMemberRoleId());
        Wrapper<MemberFeignQueryVO> memberFeignQueryVOWrapper = memberInnerControllerFeign.getMemberInfo(memberRelationFeignVO);
        if(memberFeignQueryVOWrapper==null){
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(memberFeignQueryVOWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(memberFeignQueryVOWrapper);
        }
        CreditApplyMemberVO memberVO = new CreditApplyMemberVO();
        memberVO.setApplyNo("");
        if (memberFeignQueryVOWrapper.getData() != null) {
            memberVO.setParentMemberName(memberFeignQueryVOWrapper.getData().getMemberName());
            memberVO.setRoleName(memberFeignQueryVOWrapper.getData().getRoleName());
            memberVO.setMemberTypeName(memberFeignQueryVOWrapper.getData().getMemberTypeName());
            memberVO.setLevelTag(memberFeignQueryVOWrapper.getData().getLevelTag());
            memberVO.setMemberName(memberFeignQueryVOWrapper.getData().getSubMemberName());

            // 查询log
            List<Long> memberIds = new ArrayList<>();
            memberIds.add(creditDo.getParentMemberId());
            Wrapper<List<MemberFeignLogoVO>> logListWrapper = memberInnerControllerFeign.getMemberLogos(memberIds);
            if(logListWrapper==null){
                return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
            }else if(logListWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
                return Wrapper.fail(logListWrapper);
            }
            logListWrapper.getData().stream().filter(item -> item.getMemberId().equals(creditDo.getParentMemberId())).findFirst().ifPresent(memberLogQueryVO -> memberVO.setParentMemberLog(memberLogQueryVO.getLogo()));
        }
        // 只要非冻结状态，其他状态返回正常
        if (CreditStatusEnum.FROZEN.getCode().equals(creditDo.getStatus())) {
            memberVO.setStatus(creditDo.getStatus());
        } else {
            memberVO.setStatus(CreditStatusEnum.THAW.getCode());
        }
        memberVO.setOuterStatus(CreditApplyOuterStatusEnum.WAIT_SUBMIT.getCode());
        memberVO.setInnerStatus(CreditApplySuperiorInnerStatusEnum.WAIT_SUBMIT.getCode());
        // 赋值授信会员信息
        result.setMember(memberVO);

        CreditApplyVO applyVO = new CreditApplyVO();
        applyVO.setOriginalQuota(creditDo.getQuota());
        applyVO.setApplyQuota(creditDo.getQuota());
        PaymentParameterFeignDetailVO payParameters = feignService.getCreditPayment(creditDo.getParentMemberId(), creditDo.getParentMemberRoleId());
        if(payParameters == null || CollectionUtils.isEmpty(payParameters.getParameters())) {
            return Wrapper.fail(ResponseCode.PAY_MEMBER_PARAMETERS_DOES_NOT_EXIST);
        }

        //上调额度
        PayChannelParameterFeignDetailVO detailVO = payParameters.getParameters().stream().filter(p -> p.getParameter().equals(OrderPaymentParameterEnum.CREDIT_QUOTA_INCREAMENT) && StringUtils.hasLength(p.getValue())).findFirst().orElse(null);
        double incrementParameter = detailVO == null ? 0D : Double.parseDouble(detailVO.getValue());
        if (creditDo.getQuota() > 0) {
            // 如果原有额度大于0，申请额度自动上调
            applyVO.setApplyQuota(creditDo.getQuota() * (100 + incrementParameter) / 100);
        } else {
            PayChannelParameterFeignDetailVO initQuota = payParameters.getParameters().stream().filter(p -> p.getParameter().equals(OrderPaymentParameterEnum.CREDIT_APPLY_AMOUNT) && StringUtils.hasLength(p.getValue())).findFirst().orElse(null);
            if(initQuota!=null&&initQuota.getValue()!=null){
                applyVO.setApplyQuota(Double.parseDouble(initQuota.getValue()));
            }else{
                applyVO.setApplyQuota(0D);
            }
        }

        applyVO.setUseQuota(creditDo.getUseQuota());
        applyVO.setBillDay(creditDo.getBillDay());
        applyVO.setRepayPeriod(creditDo.getRepayPeriod());
        applyVO.setApplyTime("");
        applyVO.setApplyType(CreditApplyTypeEnum.OUTER.getCode());
        // 赋值授信申请信息
        result.setApply(applyVO);

        // 赋值历史授信申请信息
        List<CreditHistoryApplyVO> applyHistoryList = getHistoryApplyList(creditDo.getId(), isUpperSle);
        result.setHistoryApplyList(applyHistoryList);

        // 非新增时，直接查询数据
        if (getDetailVO.getApplyId() > 0) {
            // 获取授信申请信息
            CreditApplyDO applyDO = applyRepository.findById(getDetailVO.getApplyId()).orElse(null);
            if (applyDO == null) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
            }
            if (!applyDO.getCreditId().equals(creditDo.getId())) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
            }

            // 赋值授信申请单外部流转
            List<CreditApplyTaskStepVO> outerTaskList = new ArrayList<>();
            CreditApplyTaskStepVO outerTaskStepVO = new CreditApplyTaskStepVO();

            if (CreditApplyTypeEnum.OUTER.getCode().equals(applyDO.getApplyType())) {
                outerTaskStepVO=buildCreditApplyTaskStepVO(1,"提交授信申请单","采购商",applyDO.getOuterStatus() >= CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode() ? CommonBooleanEnum.YES.getCode() : CommonBooleanEnum.NO.getCode());
            } else if (CreditApplyTypeEnum.INNER.getCode().equals(applyDO.getApplyType())) {
                outerTaskStepVO=buildCreditApplyTaskStepVO(1,"提交授信调额","供应商",CommonBooleanEnum.YES.getCode());
            }
            outerTaskList.add(outerTaskStepVO);
            outerTaskStepVO=buildCreditApplyTaskStepVO(2,"确认授信申请单","供应商",applyDO.getOuterStatus() >= CreditApplyOuterStatusEnum.ACCEPT_APPLY.getCode() ? CommonBooleanEnum.YES.getCode() : CommonBooleanEnum.NO.getCode());
            outerTaskList.add(outerTaskStepVO);

            // 申请类型为外部类型时，或申请类型为外部或（申请类型为内部且是上级查询），组装外部流转
            if (CreditApplyTypeEnum.OUTER.getCode().equals(applyDO.getApplyType())
                    || (CreditApplyTypeEnum.INNER.getCode().equals(applyDO.getApplyType()) && isUpperSle)
            ) {
                result.setOuterTaskList(outerTaskList);
            }

            // 赋值授信会员信息
            result.getMember().setApplyNo(applyDO.getApplyNo());
            if (isUpperSle) {
                result.getMember().setInnerStatus(applyDO.getSuperiorInnerStatus());
                result.getMember().setInnerStatusName(CreditApplySuperiorInnerStatusEnum.getItemMessage(applyDO.getSuperiorInnerStatus()));
            } else {
                result.getMember().setInnerStatus(applyDO.getLowerInnerStatus());
                result.getMember().setInnerStatusName(CreditApplyLowerInnerStatusEnum.getItemMessage(applyDO.getLowerInnerStatus()));
            }
            result.getMember().setOuterStatus(applyDO.getOuterStatus());
            result.getMember().setOuterStatusName(CreditApplyOuterStatusEnum.getItemMessage(applyDO.getOuterStatus()));

            // 赋值授信申请信息
            result.getApply().setApplyType(applyDO.getApplyType());
            result.getApply().setBillDay(applyDO.getBillDay());
            result.getApply().setRepayPeriod(applyDO.getRepayPeriod());
            result.getApply().setOriginalQuota(applyDO.getOriginalQuota());
            result.getApply().setApplyQuota(applyDO.getApplyQuota());
            result.getApply().setApplyTime(DateUtil.format(DateUtil.date(applyDO.getApplyTime()), "yyyy-MM-dd HH:mm"));
            result.getApply().setFileList(applyDO.getFileList());

            // 赋值授信审批信息
            Wrapper<CreditVerifyVO> creditVerifyVOWrapper = verifyService.getVerify(applyDO.getId());
            CreditVerifyVO creditVerifyVO = creditVerifyVOWrapper.getData();
            if (creditVerifyVO == null) {
                creditVerifyVO = new CreditVerifyVO();
                creditVerifyVO.setBillDay(applyDO.getBillDay());
                creditVerifyVO.setQuota(applyDO.getApplyQuota());
                creditVerifyVO.setMaxApplyQuota(applyDO.getApplyQuota());
                creditVerifyVO.setRepayPeriod(applyDO.getRepayPeriod());
                creditVerifyVO.setVerifyTime("");
            }

            // 根据支付配置，调整最大申请额度
            // 如果已申请过，则在原有的金额上上升幅度
            Double maxApplyQuota = creditDo.getQuota().compareTo(0D) > 0 ? creditDo.getQuota() * (100 + incrementParameter) / 100 : applyVO.getApplyQuota();
            creditVerifyVO.setMaxApplyQuota(maxApplyQuota);
            result.setVerify(creditVerifyVO);

            // 赋值外部单据流转记录
            Wrapper<List<CreditOuterVerifyRecordVO>> outerVerifyRecordVOWrapper = outerVerifyRecordService.getHistoryList(applyDO.getId());
            if(outerVerifyRecordVOWrapper==null){
                return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
            }else if(outerVerifyRecordVOWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
                return Wrapper.fail(outerVerifyRecordVOWrapper);
            }
            result.setOuterVerifyRecordList(outerVerifyRecordVOWrapper.getData());

            // 上级查询为真时，查询内部流转
            if (isUpperSle) {
                // 查询内部工作流步骤
                InternalProcessQueryVO queryVO=new InternalProcessQueryVO();
                queryVO.setMemberId(applyDO.getMemberId());
                queryVO.setTaskId(applyDO.getInnerTaskId());
                queryVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
                Wrapper<SimpleProcessDefVO> listTaskStep = processFeign.findSimpleInternalTaskDefinitions(queryVO);
                if(listTaskStep==null){
                    return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
                }else if(listTaskStep.getCode() != ResponseCode.SUCCESS.getCode()){
                    return Wrapper.fail(listTaskStep);
                }
                // 赋值授信申请单内部流转
                Integer currentStep = listTaskStep.getData().getCurrentStep();
                List<CreditApplyTaskStepVO> innerTaskList = listTaskStep.getData().getTasks().stream().map(r -> {
                    CreditApplyTaskStepVO taskStepVO = new CreditApplyTaskStepVO();
                    taskStepVO.setStep(r.getTaskStep());
                    taskStepVO.setTaskName(r.getTaskName());
                    taskStepVO.setRoleName(r.getRoleName());
                    // 对应工作流步骤小于等于当前执行最后一步时，则标记已执行
                    if (r.getTaskStep() <=currentStep||currentStep==0) {
                        taskStepVO.setIsExecute(CommonBooleanEnum.YES.getCode());
                    } else {
                        taskStepVO.setIsExecute(CommonBooleanEnum.NO.getCode());
                    }
                    return taskStepVO;
                }).collect(Collectors.toList());
                result.setInnerTaskList(innerTaskList);

                // 赋值内部单据流转记录
                Wrapper<List<CreditInnerVerifyRecordVO>> innerVerifyRecordVOWrapper = innerVerifyRecordService.getHistoryList(applyDO.getId());
                if (innerVerifyRecordVOWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                    return Wrapper.fail(innerVerifyRecordVOWrapper);
                }
                result.setInnerVerifyRecordList(innerVerifyRecordVOWrapper.getData());
            }
        }else{
            //添加是的外部流转
            CreditApplyTaskStepVO step1=buildCreditApplyTaskStepVO(1,"提交授信申请单","采购商", CommonBooleanEnum.NO.getCode());
            CreditApplyTaskStepVO step2=buildCreditApplyTaskStepVO(2,"确认授信申请单","供应商", CommonBooleanEnum.NO.getCode());
            List<CreditApplyTaskStepVO> outerTaskList = new ArrayList<>();
            outerTaskList.add(step1);
            outerTaskList.add(step2);
            result.setOuterTaskList(outerTaskList);
        }

        return Wrapper.success(result);
    }

    /**
     * 获取授信申请历史
     * @author 伍将
     * @date 2020/8/21
     * @param creditId:
     * @return com.ssy.lingxi.common.response.Wrapper<java.util.List < com.ssy.lingxi.pay.model.vo.response.CreditHistoryApplyVO>>
     **/
    @Override
    public Wrapper<List<CreditHistoryApplyVO>> getHistoryList(Long creditId, Boolean isUpperSle) {
        return Wrapper.success(getHistoryApplyList(creditId, isUpperSle));
    }

    /**
     * 分页查询子会员授信申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildApply(UserLoginCacheDTO user, PageQueryLowerCreditApplyVO pageVO) {

        // 查询会员信息
        MemberFeignSubVO memberFeignVO = new MemberFeignSubVO();
        memberFeignVO.setMemberId(user.getMemberId());
        memberFeignVO.setRoleId(user.getMemberRoleId());
        memberFeignVO.setSubMemberName(pageVO.getMemberName());
        memberFeignVO.setLevel(pageVO.getLevel());
        memberFeignVO.setMemberTypeId(pageVO.getMemberTypeId());
        memberFeignVO.setSubRoleId(pageVO.getSubRoleId());
        Wrapper<List<MemberFeignQueryVO>> listWrapper = memberInnerControllerFeign.listLowerMembers(memberFeignVO);
        if (listWrapper != null && listWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(listWrapper);
        }
        List<Long> idList = listWrapper.getData().stream().map(MemberFeignQueryVO::getMemberId).collect(Collectors.toList());

        // step 1: 组装查询条件
        Specification<CreditApplyDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 默认查询未删除状态
            list.add(criteriaBuilder.equal(root.get("isDelete").as(Long.class), CommonBooleanEnum.NO.getCode()));
            // 默认查询当前申请状态
            list.add(criteriaBuilder.equal(root.get("isCurrent").as(Integer.class), CommonBooleanEnum.YES.getCode()));
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));

            if (pageVO.getOuterStatus() != null
                    && !pageVO.getOuterStatus().equals(CreditApplyOuterStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (null != pageVO.getInnerStatus()
                    && !CreditApplySuperiorInnerStatusEnum.ALL.getCode().equals(pageVO.getInnerStatus())) {
                list.add(criteriaBuilder.equal(root.get("superiorInnerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }

            // 增加会员筛选条件
            if (StringUtils.hasLength(pageVO.getMemberName())
                    || null != pageVO.getMemberTypeId()
                    || null != pageVO.getSubRoleId()
                    || null != pageVO.getLevel()) {
                list.add(criteriaBuilder.in(root.get("memberId")).value(idList));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());

        // step 3: 分页查询数据
        Page<CreditApplyDO> result = this.applyRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<CreditChildApplyPageQueryVO> resultList = result.getContent().stream().map(r -> {
            CreditChildApplyPageQueryVO queryVO = new CreditChildApplyPageQueryVO();
            queryVO.setCreditId(r.getCreditId());
            queryVO.setId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            MemberFeignQueryVO memberFeignQueryVO = listWrapper.getData().stream().filter(item ->
                    item.getMemberId().equals(r.getMemberId())
                            && item.getRoleId().equals(r.getRoleId())).findFirst().orElse(null);
            if (memberFeignQueryVO != null) {
                queryVO.setMemberName(memberFeignQueryVO.getMemberName());
                queryVO.setMemberTypeName(memberFeignQueryVO.getMemberTypeName());
                queryVO.setMemberRoleName(memberFeignQueryVO.getRoleName());
                queryVO.setMemberLevelName(memberFeignQueryVO.getLevelTag());
            }
            queryVO.setOriginalQuota(r.getOriginalQuota());
            queryVO.setApplyQuota(r.getApplyQuota());
            queryVO.setInnerStatus(r.getSuperiorInnerStatus());
            queryVO.setInnerStatusName(CreditApplySuperiorInnerStatusEnum.getItemMessage(r.getSuperiorInnerStatus()));
            queryVO.setOuterStatus(r.getOuterStatus());
            queryVO.setOuterStatusName(CreditApplyOuterStatusEnum.getItemMessage(r.getOuterStatus()));
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 获取子会员申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @param innerStatusList: 内部状态
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditApplyPageQueryVO>>
     **/
    private Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildApplyByHandle(UserLoginCacheDTO user, PageQueryCreditChildApplyVO pageVO, List<Integer> innerStatusList) {

        // 查询会员信息
        MemberFeignSubVO memberFeignVO = new MemberFeignSubVO();
        memberFeignVO.setMemberId(user.getMemberId());
        memberFeignVO.setRoleId(user.getMemberRoleId());
        memberFeignVO.setSubMemberName(pageVO.getMemberName());
        memberFeignVO.setLevel(pageVO.getLevel());
        memberFeignVO.setMemberTypeId(pageVO.getMemberTypeId());
        memberFeignVO.setSubRoleId(pageVO.getSubRoleId());
        Wrapper<List<MemberFeignQueryVO>> listWrapper = memberInnerControllerFeign.listLowerMembers(memberFeignVO);
        if(listWrapper==null){
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }
        if (listWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(listWrapper);
        }
        List<Long> idList = listWrapper.getData().stream().map(MemberFeignQueryVO::getMemberId).collect(Collectors.toList());

        // step 1: 组装查询条件
        Specification<CreditApplyDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 默认查询未删除状态
            list.add(criteriaBuilder.equal(root.get("isDelete").as(Long.class), CommonBooleanEnum.NO.getCode()));
            // 默认查询当前申请状态
            list.add(criteriaBuilder.equal(root.get("isCurrent").as(Integer.class), CommonBooleanEnum.YES.getCode()));
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("outerStatus").as(Long.class), CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode()));

            if (innerStatusList != null && innerStatusList.size() > 0) {
                CriteriaBuilder.In<Object> in = criteriaBuilder.in(root.get("superiorInnerStatus"));
                for (Integer id : innerStatusList) {
                    in.value(id);
                }
                list.add(in);
            }
            if (pageVO.getApplyType() > CreditApplyTypeEnum.ALL.getCode()) {
                list.add(criteriaBuilder.equal(root.get("applyType").as(Integer.class), pageVO.getApplyType()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            // 增加会员筛选条件
            if (StringUtils.hasLength(pageVO.getMemberName())
                    || null != pageVO.getMemberTypeId()
                    || null != pageVO.getSubRoleId()
                    || null != pageVO.getLevel()) {
                list.add(criteriaBuilder.in(root.get("memberId")).value(idList));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());

        // step 3: 分页查询数据
        Page<CreditApplyDO> result = this.applyRepository.findAll(spec, page);


        // step 4: 组装返回数据
        List<CreditChildApplyPageQueryVO> resultList = result.getContent().stream().map(r -> {
            CreditChildApplyPageQueryVO queryVO = new CreditChildApplyPageQueryVO();
            queryVO.setCreditId(r.getCreditId());
            queryVO.setId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            MemberFeignQueryVO memberFeignQueryVO = listWrapper.getData().stream().filter(item ->
                    item.getMemberId().equals(r.getMemberId())
                            && item.getRoleId().equals(r.getRoleId())).findFirst().orElse(null);
            if (memberFeignQueryVO != null) {
                queryVO.setMemberName(memberFeignQueryVO.getMemberName());
                queryVO.setMemberTypeName(memberFeignQueryVO.getMemberTypeName());
                queryVO.setMemberRoleName(memberFeignQueryVO.getRoleName());
                queryVO.setMemberLevelName(memberFeignQueryVO.getLevelTag());
            }
            queryVO.setOriginalQuota(r.getOriginalQuota());
            queryVO.setApplyQuota(r.getApplyQuota());
            queryVO.setInnerStatus(r.getSuperiorInnerStatus());
            queryVO.setInnerStatusName(CreditApplySuperiorInnerStatusEnum.getItemMessage(r.getSuperiorInnerStatus()));
            queryVO.setOuterStatus(r.getOuterStatus());
            queryVO.setOuterStatusName(CreditApplyOuterStatusEnum.getItemMessage(r.getOuterStatus()));
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setApplyTypeName(CreditApplyTypeEnum.getItemMessage(r.getApplyType()));

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 分页查询子会员待提交授信申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildWaitSubmitApply(UserLoginCacheDTO user, PageQueryCreditChildApplyVO pageVO) {

        // 查询会员信息
        MemberFeignSubVO memberFeignVO = new MemberFeignSubVO();
        memberFeignVO.setMemberId(user.getMemberId());
        memberFeignVO.setRoleId(user.getMemberRoleId());
        memberFeignVO.setSubMemberName(pageVO.getMemberName());
        memberFeignVO.setLevel(pageVO.getLevel());
        memberFeignVO.setMemberTypeId(pageVO.getMemberTypeId());
        memberFeignVO.setSubRoleId(pageVO.getSubRoleId());
        Wrapper<List<MemberFeignQueryVO>> listWrapper = memberInnerControllerFeign.listLowerMembers(memberFeignVO);
        if(listWrapper==null){
            return Wrapper.fail(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(listWrapper.getCode() != ResponseCode.SUCCESS.getCode()){
            return Wrapper.fail(listWrapper);
        }
        List<Long> idList = listWrapper.getData().stream().map(MemberFeignQueryVO::getMemberId).collect(Collectors.toList());

        // step 1: 组装查询条件
        Specification<CreditApplyDO> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 默认查询未删除状态
            list.add(criteriaBuilder.equal(root.get("isDelete").as(Long.class), CommonBooleanEnum.NO.getCode()));
            // 默认查询当前申请状态
            list.add(criteriaBuilder.equal(root.get("isCurrent").as(Integer.class), CommonBooleanEnum.YES.getCode()));
            list.add(criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("outerStatus").as(Long.class), CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode()));
            list.add(criteriaBuilder.equal(root.get("superiorInnerStatus").as(Long.class), CreditApplySuperiorInnerStatusEnum.WAIT_SUBMIT.getCode()));

            if (pageVO.getApplyType() > CreditApplyTypeEnum.ALL.getCode()) {
                list.add(criteriaBuilder.equal(root.get("applyType").as(Integer.class), pageVO.getApplyType()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            // 筛选会员名称
            if (StringUtils.hasLength(pageVO.getMemberName())) {
                List<Long> idList1 = listWrapper.getData().stream()
                        .filter(r -> r.getMemberName().contains(pageVO.getMemberName()))
                        .map(MemberFeignQueryVO::getMemberId).collect(Collectors.toList());
                list.add(criteriaBuilder.in(root.get("memberId")).value(idList1));
            }
            // 增加会员筛选条件
            if (StringUtils.hasLength(pageVO.getMemberName())
                    || null != pageVO.getMemberTypeId()
                    || null != pageVO.getSubRoleId()
                    || null != pageVO.getLevel()) {
                list.add(criteriaBuilder.in(root.get("memberId")).value(idList));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());

        // step 3: 分页查询数据
        Page<CreditApplyDO> result = this.applyRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<CreditChildApplyPageQueryVO> resultList = result.getContent().stream().map(r -> {
            CreditChildApplyPageQueryVO queryVO = new CreditChildApplyPageQueryVO();
            queryVO.setCreditId(r.getCreditId());
            queryVO.setId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            MemberFeignQueryVO memberFeignQueryVO = listWrapper.getData().stream().filter(item ->
                    item.getMemberId().equals(r.getMemberId())
                            && item.getRoleId().equals(r.getRoleId())).findFirst().orElse(null);
            if (memberFeignQueryVO != null) {
                queryVO.setMemberName(memberFeignQueryVO.getMemberName());
                queryVO.setMemberTypeName(memberFeignQueryVO.getMemberTypeName());
                queryVO.setMemberRoleName(memberFeignQueryVO.getRoleName());
                queryVO.setMemberLevelName(memberFeignQueryVO.getLevelTag());
            }
            queryVO.setOriginalQuota(r.getOriginalQuota());
            queryVO.setApplyQuota(r.getApplyQuota());
            queryVO.setInnerStatus(r.getSuperiorInnerStatus());
            queryVO.setInnerStatusName(CreditApplySuperiorInnerStatusEnum.getItemMessage(r.getSuperiorInnerStatus()));
            queryVO.setOuterStatus(r.getOuterStatus());
            queryVO.setOuterStatusName(CreditApplyOuterStatusEnum.getItemMessage(r.getOuterStatus()));
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setApplyTypeName(CreditApplyTypeEnum.getItemMessage(r.getApplyType()));

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 分页查询子会员待审核第一步申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditChildApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildWaitVerifyApplyStepOne(UserLoginCacheDTO user, PageQueryCreditChildApplyVO pageVO) {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(CreditApplySuperiorInnerStatusEnum.SUBMIT_VERIFY_SUCCESS.getCode());

        return pageChildApplyByHandle(user, pageVO, statusList);
    }

    /**
     * 一级审核
     * @author 伍将
     * @date 2020/10/17
     * @param user:
     * @param verifyVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepOne(UserLoginCacheDTO user, CreditApplyVerifyVO verifyVO) {

        CreditApplyDO applyDO = applyRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 外部状态不等于待确认，内部状态不等于提交审核成功，不允许一级审核
        if (!CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode().equals(applyDO.getOuterStatus())
                || !CreditApplySuperiorInnerStatusEnum.SUBMIT_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())
        ) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_WAIT_VERIFY);
        }
        // 所属授信必须存在
        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 授信申请单审核流转
        TaskExecuteVO taskExecuteVO=new TaskExecuteVO();
        taskExecuteVO.setMemberId(creditDO.getMemberId());
        taskExecuteVO.setRoleId(creditDO.getMemberRoleId());
        taskExecuteVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
        taskExecuteVO.setTaskId(applyDO.getInnerTaskId());
        taskExecuteVO.setAgree(verifyVO.getIsPass());
        taskExecuteVO.setDataId(applyDO.getId());
        Wrapper<SimpleTaskCompleteVO> taskResultVOWrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == taskResultVOWrapper.getCode()) {
            applyDO.setSuperiorInnerStatus(taskResultVOWrapper.getData().getStatus());
            applyDO.setInnerTaskId(taskResultVOWrapper.getData().getTaskId());
            applyDO.setInnerTaskStep(taskResultVOWrapper.getData().getStep());
            applyDO.setUpdateTime(System.currentTimeMillis());
            applyRepository.saveAndFlush(applyDO);

            // 新增内部流转记录
            addCreditInnerVerifyRecord(applyDO, user, verifyVO.getOpinion(), applyDO.getInnerTaskStep(),CreditApplySuperiorActionEnum.getItemMessage(applyDO.getInnerTaskStep()));

            // 授信处理待审核授信申请单（一级）-1,待审核授信申请单（二级）+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(applyDO.getParentMemberId());
            noticeVO.setRoleId(applyDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.CREDIT.getCode());
            CreditOperateTypeEnum typeEnum = (CreditApplySuperiorInnerStatusEnum.STEP1_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus()) ? CreditOperateTypeEnum.TO_BE_VALIFY_STEP2 : CreditOperateTypeEnum.TO_BE_CONFIRM);
            noticeVO.setIncreaseOperateType(typeEnum.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceOperateType(CreditOperateTypeEnum.TO_BE_VALIFY_STEP1.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            feignService.addSysOperateNotice(noticeVO);

            // 新增待审核授信申请单（二级）/待确认授信申请单消息通知
            MemberRelationFeignVO feignVO = new MemberRelationFeignVO();
            feignVO.setUpperMemberId(applyDO.getParentMemberId());
            feignVO.setUpperRoleId(applyDO.getParentMemberRoleId());
            feignVO.setMemberId(applyDO.getMemberId());
            feignVO.setRoleId(applyDO.getRoleId());
            Wrapper<MemberFeignQueryVO> memberWrapper = memberInnerControllerFeign.getMemberInfo(feignVO);
            if (null != memberWrapper && memberWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != memberWrapper.getData()) {
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(applyDO.getParentMemberId());
                request.setRoleId(applyDO.getParentMemberRoleId());
                String messageTemplateCode = (CreditApplySuperiorInnerStatusEnum.STEP1_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())
                        ? MessageTemplateCode.credit_handle_audit_2 : MessageTemplateCode.credit_handle_submit);
                request.setMessageNotice(messageTemplateCode);
                List<String> params = new ArrayList<>();
                params.add(memberWrapper.getData().getMemberName());
                params.add(applyDO.getApplyNo());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        } else {
            return Wrapper.fail(taskResultVOWrapper);
        }

        return Wrapper.success();
    }

    /**
     * 二级审核
     * @author 伍将
     * @date 2020/10/17
     * @param user:
     * @param verifyVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepTwo(UserLoginCacheDTO user, CreditApplyVerifyVO verifyVO) {
        CreditApplyDO applyDO = applyRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 外部状态不等于待确认，内部状态不等于一级审核成功，不允许二级审核
        if (!CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode().equals(applyDO.getOuterStatus())
                || !CreditApplySuperiorInnerStatusEnum.STEP1_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_WAIT_VERIFY);
        }
        // 所属授信必须存在
        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 授信申请单审核流转
        TaskExecuteVO taskExecuteVO=new TaskExecuteVO();
        taskExecuteVO.setMemberId(creditDO.getMemberId());
        taskExecuteVO.setRoleId(creditDO.getMemberRoleId());
        taskExecuteVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
        taskExecuteVO.setTaskId(applyDO.getInnerTaskId());
        taskExecuteVO.setAgree(verifyVO.getIsPass());
        taskExecuteVO.setDataId(applyDO.getId());
        Wrapper<SimpleTaskCompleteVO> taskResultVOWrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == taskResultVOWrapper.getCode()) {
            applyDO.setSuperiorInnerStatus(taskResultVOWrapper.getData().getStatus());
            applyDO.setInnerTaskId(taskResultVOWrapper.getData().getTaskId());
            applyDO.setInnerTaskStep(taskResultVOWrapper.getData().getStep());
            applyDO.setUpdateTime(System.currentTimeMillis());
            applyRepository.saveAndFlush(applyDO);

            // 新增内部流转记录
            addCreditInnerVerifyRecord(applyDO, user, verifyVO.getOpinion(), applyDO.getInnerTaskStep(), CreditApplySuperiorActionEnum.getItemMessage(applyDO.getInnerTaskStep()));

            // 授信处理待审核授信申请单（二级）-1,待审核授信申请单（三级）+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(applyDO.getParentMemberId());
            noticeVO.setRoleId(applyDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.CREDIT.getCode());
            CreditOperateTypeEnum typeEnum = (CreditApplySuperiorInnerStatusEnum.STEP2_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus()) ? CreditOperateTypeEnum.TO_BE_VALIFY_STEP3 : CreditOperateTypeEnum.TO_BE_CONFIRM);
            noticeVO.setIncreaseOperateType(typeEnum.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceOperateType(CreditOperateTypeEnum.TO_BE_VALIFY_STEP2.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            feignService.addSysOperateNotice(noticeVO);

            // 新增待审核授信申请单（三级）/待确认授信申请单消息通知
            MemberRelationFeignVO feignVO = new MemberRelationFeignVO();
            feignVO.setUpperMemberId(applyDO.getParentMemberId());
            feignVO.setUpperRoleId(applyDO.getParentMemberRoleId());
            feignVO.setMemberId(applyDO.getMemberId());
            feignVO.setRoleId(applyDO.getRoleId());
            Wrapper<MemberFeignQueryVO> memberWrapper = memberInnerControllerFeign.getMemberInfo(feignVO);
            if (null != memberWrapper && memberWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != memberWrapper.getData()) {
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(applyDO.getParentMemberId());
                request.setRoleId(applyDO.getParentMemberRoleId());
                String messageTemplateCode = (CreditApplySuperiorInnerStatusEnum.STEP2_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())
                        ? MessageTemplateCode.credit_handle_audit_3 : MessageTemplateCode.credit_handle_submit);
                request.setMessageNotice(messageTemplateCode);
                List<String> params = new ArrayList<>();
                params.add(memberWrapper.getData().getMemberName());
                params.add(applyDO.getApplyNo());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        } else {
            return Wrapper.fail(taskResultVOWrapper);
        }

        return Wrapper.success();
    }

    /**
     * 三级审核
     * @author 伍将
     * @date 2020/10/17
     * @param user:
     * @param verifyVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> verifyStepThree(UserLoginCacheDTO user, CreditApplyVerifyVO verifyVO) {
        CreditApplyDO applyDO = applyRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (applyDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_NOT_EXIST);
        }
        // 外部状态不等于待确认，内部状态不等于二级审核成功，不允许三级审核
        if (!CreditApplyOuterStatusEnum.WAIT_CONFIRM.getCode().equals(applyDO.getOuterStatus())
                || !CreditApplySuperiorInnerStatusEnum.STEP2_VERIFY_SUCCESS.getCode().equals(applyDO.getSuperiorInnerStatus())
        ) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_APPLY_CAN_NOT_WAIT_VERIFY);
        }
        // 所属授信必须存在
        CreditDO creditDO = creditRepository.findById(applyDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }

        // 授信申请单审核流转
        TaskExecuteVO taskExecuteVO=new TaskExecuteVO();
        taskExecuteVO.setMemberId(creditDO.getMemberId());
        taskExecuteVO.setRoleId(creditDO.getMemberRoleId());
        taskExecuteVO.setProcessKey(ProcessEnum.getProcessKeyByCode(applyDO.getInnerTaskType()));
        taskExecuteVO.setTaskId(applyDO.getInnerTaskId());
        taskExecuteVO.setAgree(verifyVO.getIsPass());
        taskExecuteVO.setDataId(applyDO.getId());
        Wrapper<SimpleTaskCompleteVO> taskResultVOWrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == taskResultVOWrapper.getCode()) {
            applyDO.setSuperiorInnerStatus(taskResultVOWrapper.getData().getStatus());
            applyDO.setInnerTaskId(taskResultVOWrapper.getData().getTaskId());
            applyDO.setInnerTaskStep(taskResultVOWrapper.getData().getStep());
            applyDO.setUpdateTime(System.currentTimeMillis());
            applyRepository.saveAndFlush(applyDO);

            // 新增内部流转记录
            addCreditInnerVerifyRecord(applyDO, user, verifyVO.getOpinion(), applyDO.getInnerTaskStep(), CreditApplySuperiorActionEnum.getItemMessage(applyDO.getInnerTaskStep()));

            // 授信处理待审核授信申请单（三级）-1,待确认授信申请单+1
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(applyDO.getParentMemberId());
            noticeVO.setRoleId(applyDO.getParentMemberRoleId());
            noticeVO.setDataSource(OperateDataSourceEnum.CREDIT.getCode());
            noticeVO.setIncreaseOperateType(CreditOperateTypeEnum.TO_BE_CONFIRM.getCode());
            noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            noticeVO.setReduceOperateType(CreditOperateTypeEnum.TO_BE_VALIFY_STEP3.getCode());
            noticeVO.setReduceCount(Constants.SYS_OPERATE_NOTICE_COUNT);
            feignService.addSysOperateNotice(noticeVO);

            // 新增待确认授信申请单消息通知
            MemberRelationFeignVO feignVO = new MemberRelationFeignVO();
            feignVO.setUpperMemberId(applyDO.getParentMemberId());
            feignVO.setUpperRoleId(applyDO.getParentMemberRoleId());
            feignVO.setMemberId(applyDO.getMemberId());
            feignVO.setRoleId(applyDO.getRoleId());
            Wrapper<MemberFeignQueryVO> memberWrapper = memberInnerControllerFeign.getMemberInfo(feignVO);
            if (null != memberWrapper && memberWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != memberWrapper.getData()) {
                SystemMessageRequest request = new SystemMessageRequest();
                request.setMemberId(applyDO.getParentMemberId());
                request.setRoleId(applyDO.getParentMemberRoleId());
                request.setMessageNotice(MessageTemplateCode.credit_handle_submit);
                List<String> params = new ArrayList<>();
                params.add(memberWrapper.getData().getMemberName());
                params.add(applyDO.getApplyNo());
                request.setParams(params);
                feignService.sendSystemMessage(request);
            }
        } else {
            return Wrapper.fail(taskResultVOWrapper);
        }

        return Wrapper.success();
    }

    /**
     * 分页查询子会员待审核第二步申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditChildApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildWaitVerifyApplyStepTwo(UserLoginCacheDTO user, PageQueryCreditChildApplyVO pageVO) {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(CreditApplySuperiorInnerStatusEnum.STEP1_VERIFY_SUCCESS.getCode());

        return pageChildApplyByHandle(user, pageVO, statusList);
    }

    /**
     * 分页查询子会员待审核第三步申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditChildApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildWaitVerifyApplyStepThree(UserLoginCacheDTO user, PageQueryCreditChildApplyVO pageVO) {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(CreditApplySuperiorInnerStatusEnum.STEP2_VERIFY_SUCCESS.getCode());

        return pageChildApplyByHandle(user, pageVO, statusList);
    }

    /**
     * 分页查询子会员待确认审核申请
     * @author 伍将
     * @date 2020/8/26
     * @param user:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditChildApplyPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditChildApplyPageQueryVO>> pageChildWaitConfirmVerifyApply(UserLoginCacheDTO user, PageQueryCreditChildApplyVO pageVO) {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(CreditApplySuperiorInnerStatusEnum.STEP3_VERIFY_SUCCESS.getCode());
        statusList.add(CreditApplySuperiorInnerStatusEnum.SUBMIT_VERIFY_FAIL.getCode());
        statusList.add(CreditApplySuperiorInnerStatusEnum.STEP1_VERIFY_FAIL.getCode());
        statusList.add(CreditApplySuperiorInnerStatusEnum.STEP2_VERIFY_FAIL.getCode());
        statusList.add(CreditApplySuperiorInnerStatusEnum.STEP3_VERIFY_FAIL.getCode());

        return pageChildApplyByHandle(user, pageVO, statusList);
    }

    /**
     *  获取历史授信申请
     * @author 伍将
     * @date 2020/8/18
     * @param creditId: 授信id
     * @param isUpperSel:是否上级查询
     * @return java.util.List<com.ssy.lingxi.pay.entity.CreditApplyDO>
     **/
    private List<CreditHistoryApplyVO> getHistoryApplyList(Long creditId, Boolean isUpperSel) {
        List<CreditApplyDO> applyDOList = applyRepository.findByCreditIdAndIsDeleteOrderByApplyTimeDesc(creditId, CommonBooleanEnum.NO.getCode());

        return applyDOList.stream().map(r -> {
            CreditHistoryApplyVO queryVO = new CreditHistoryApplyVO();
            queryVO.setCreditId(creditId);
            queryVO.setId(r.getId());
            queryVO.setApplyNo(r.getApplyNo());
            queryVO.setOriginalQuota(r.getOriginalQuota());
            queryVO.setApplyQuota(r.getApplyQuota());
            queryVO.setAuditQuota(r.getAuditQuota());
            queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));

            return queryVO;
        }).collect(Collectors.toList());
    }

    /**
     * 查询调额记录
     * @author 伍将
     * @date 2021/3/9
     * @param user: 当前登录会员
     * @param creditId: 授信id
     * @return 操作结果
     **/
    @Override
    public Wrapper<List<CreditAdjustQuotaRecordVO>> getAdjustQuotaList(UserLoginCacheDTO user, Long creditId) {

        // step 1: 组装查询条件
        Specification<CreditApplyDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 查询未删除状态
            list.add(criteriaBuilder.equal(root.get("isDelete").as(Long.class), CommonBooleanEnum.NO.getCode()));
            list.add(criteriaBuilder.equal(root.get("creditId").as(Long.class), creditId));
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), CreditApplyOuterStatusEnum.ACCEPT_APPLY.getCode()));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<CreditAdjustQuotaRecordVO> resultList = this.applyRepository
                .findAll(spec, Sort.by(Sort.Order.asc("applyTime")))
                .stream().map(r -> {
                    CreditAdjustQuotaRecordVO queryVO = new CreditAdjustQuotaRecordVO();
                    queryVO.setApplyTime(r.getApplyTime());
                    queryVO.setQuota(r.getAuditQuota());
                    return queryVO;
                }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }
}
